<?php

include_once ('bn_path.php');

class bn_module
{
    private $dl;
    private $file;
    private $up;
    protected static $instance;

    function __construct()
    {
        $this->dl = new bn_dal();
        $this->file = new bn_files;
        $this->up = new bn_upload();
    }

    public static function getInstance()
    {
        if (!isset(self::$instance))
        {
            self::$instance = new self();
        }
        return self::$instance;
    }

    private function insert($name, $dir, $mod, $menuid)
    {
        return $this->dl->insert("modules", func_get_args());
    }

    public function delete($dir)
    {
        if ($this->dl->hasrow('select dir from modules where dir=?', array($dir)))
            self::module_unistall($dir);

        $del = new bn_directory;
        $del->Delete_dir(bn_get_dir_module($dir));
        unset($del);
    }

    public function get_gad_module($id)
    {
        $row = $this->dl->getrow('select dir,module from modules where id=?', array($id))->
            fetch();
        return bn_get_dir_module('/' . $row['dir'] . "/" . $row['module']);
    }

    private function find_plugin($dir, $plugins)
    {
        for ($i = 0; $i < count($plugins); $i++)
        {
            if ($plugins[$i]['dir'] == $dir)
                return $i;
        }
        return null;
    }

    public function module_list()
    {
        $dir = new bn_directory;
        $dirs = $dir->get_dirlist(bn_get_dir_module(), 'dir');
        $plugs = $this->dl->select("select id,name,dir,('enable')active from modules")->
            fetch();
        $plugins = array();

        foreach ($dirs as $pdir)
        {
            $pdir = basename($pdir);
            $i = self::find_plugin($pdir, $plugs);
            if (empty($i))
            {
                $mydir .= bn_get_dir_module("$pdir/config.php");
                $mod_name = '';
                $mod_ver = '';
                if (file_exists($mydir))
                {
                    global $hook;
                    $hook = new bn_hookfunc;
                    include_once ($mydir);
                    $mod_name = $hook->call_function('module_name');
                    $mod_ver = $hook->call_function('module_version');
                }
                $pl = array(
                    'name' => "$mod_name  $mod_ver",
                    'dir' => $pdir,
                    'active' => 'disable');
                $plugins[] = $pl;
            } else
            {
                $plugins[] = $plugs[$i];
                unset($plugs[$i]);
            }
        }
        return $plugins;
    }

    public function module_add($file)
    {
        $dir = bn_RandomStrgenerate(16);
        $moddir = bn_get_dir_module() . "/$dir";
        mkdir($moddir, 0777, true);
        if ($this->up->upload_file($file, bn_get_dir_upload('module.zip'), 'zip') == 1)
        {
            if ($this->file->has_file_in_zipfile(bn_get_dir_upload('module.zip'),
                'config.php'))
            {
                $this->file->unzip_allfile(bn_get_dir_upload('module.zip'), $moddir);
                unlink(bn_get_dir_upload('module.zip'));
                return 1;
            }
            return 2;
        } else
            return 3;
    }

    private function sqlinfo($sql)
    {
        $sql = trim(substr($sql, 0, strpos($sql, '(')));
        $sql = explode(' ', $sql);
        $sql[2] = preg_replace("/[^a-zA-Z0-9]+/", "", $sql[2]);
        return $sql;
    }

    private function create_sqltable($sql)
    {
        if (!is_array($sql))
            $sql = explode('^', $sql);

        foreach ($sql as $cmd)
        {
            $cmd = trim($cmd);
            $info = self::sqlinfo($cmd);
            if (strtolower($info[0]) == 'create' && strtolower($info[1]) == 'table')
            {
                $table = $this->dl->Tables($info[2]);
                if (empty($table))
                    $this->dl->query($cmd);
            } else
                $this->dl->query($cmd);
        }
    }

    private function create_modulemenu($menu, $dir)
    {
        if (!empty($menu))
        {
            $path = root . '/admin/mod_module.php?mod_admin=';
            $mnu = new bn_menu;
            $menuid = $mnu->insert('', 'admin', $menu[0][0], $path . $dir . '-' .
                str_replace('/', '-', $menu[0][1]), '');
            for ($i = 1; $i < count($menu); $i++)
            {
                $item = $menu[$i];
                $mnu->insert($menuid, 'admin', $item[0], $path . $dir . '-' . str_replace('/',
                    '-', $item[1]), '');
            }
            return $menuid;
        }
    }
    public function module_install($dir)
    {
        $mydir = bn_get_dir_module("/$dir/config.php");
        global $hook;
        $hook = new bn_hookfunc;
        include_once ($mydir);
        $mod_name = $hook->call_function('module_name');
        $mod_ver = $hook->call_function('module_version');
        $mod_gad = $hook->call_function('module_gadget');
        $sql = $hook->call_function('module_sql');

        if (!empty($sql))
            self::create_sqltable($sql);
        $menu = $hook->call_function('module_menu');
        $menuid = self::create_modulemenu($menu, $dir);
        self::insert($mod_name, $dir, $mod_gad, $menuid);
        unset($hook);
    }

    public function module_unistall($dir)
    {
        $row = $this->dl->getrow('select menuid from modules where dir=?', array($dir))->
            fetch();
        $this->dl->delete('modules', $dir, 'dir');
        $this->dl->query("delete from menus where id=? or pid=?", array($row['menuid'],
                $row['menuid']));
        $plugdir = bn_get_dir_module($dir);
        $mydir = bn_get_dir_module("/$dir/config.php");
        global $hook;
        $hook = new bn_hookfunc;
        include_once ($mydir);
        $del = $hook->call_function('sql_delete');
        self::create_sqltable($del);
        unset($hook);
    }

    public function load_module($id)
    {
        ob_start();
        if (is_numeric($id))
            include_once (bn_get_dir_module(self::get_plug_module($id)));
        else
            include_once (bn_get_dir_module($id));

        return ob_get_clean();
    }
}

?>